package per.chao.mqtt.application;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.ResourceLeakDetector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import per.chao.mqtt.infrastructure.common.config.NettyMqttProperties;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * Description:
 *
 * @author W.Chao
 * @date 2021/6/19 23:08
 **/
@Component
@Slf4j
public class MqttNettyServer {
	@Autowired
	private NettyMqttProperties nettyMqttProperties;
	@Autowired
	private MqttServerChannelInitializer mqttServerChannelInitializer;

	private Channel serverChannel;
	private EventLoopGroup boosGroup;
	private EventLoopGroup workerGroup;

	@PostConstruct
	public void startup() throws InterruptedException{
		String leakDetectorLevel = nettyMqttProperties.getNetty().getLeakDetectorLevel();
		log.info("Setting resource leak detector level to {}", leakDetectorLevel);
		ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.valueOf(leakDetectorLevel.toUpperCase()));
		log.info("Starting MQTT transport...");

		log.info("Starting MQTT transport server");
		boosGroup = new NioEventLoopGroup(nettyMqttProperties.getNetty().getBossGroupThreadCount());
		workerGroup = new NioEventLoopGroup(nettyMqttProperties.getNetty().getWorkGroupThreadCount());
		ServerBootstrap b = new ServerBootstrap();
		b.group(boosGroup, workerGroup)
				.channel(NioServerSocketChannel.class)
				.childHandler(mqttServerChannelInitializer);

		String host = nettyMqttProperties.getBindAddress();
		int port = nettyMqttProperties.getListenerPort();
		log.info("Mqtt transport host: {}, port: {}", host, port);
		serverChannel = b.bind(host, port).sync().channel();

		log.info("Mqtt transport started!");
	}

	@PreDestroy
	public void close() throws InterruptedException{
		log.info("Stopping MQTT transport!");
		try {
			serverChannel.close().sync();
		} finally {
			workerGroup.shutdownGracefully();
			boosGroup.shutdownGracefully();
		}
		log.info("MQTT transport stopped!");
	}
}
